#include "Renderer.h"
#include <d3d9.h>
#include <assert.h>
LPDIRECT3D9       g_pDirect3D = NULL;

Renderer::Renderer(HWND hWnd){
	InitDX(hWnd);
}

Renderer::~Renderer(){
	g_pDirect3D_Device->Release();
	g_pDirect3D->Release();
}
bool Renderer::InitDX(HWND hWnd){
	g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);

	D3DPRESENT_PARAMETERS PresentParams;
	memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS));

	PresentParams.Windowed = TRUE;
	PresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;

	HRESULT HR = g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT,
								D3DDEVTYPE_HAL,
								hWnd,
								D3DCREATE_HARDWARE_VERTEXPROCESSING,
								&PresentParams,
								&g_pDirect3D_Device);
	HR = NULL;

	D3DVIEWPORT9 viewport;
	g_pDirect3D_Device->GetViewport(&viewport);

	D3DXMatrixOrthoLH(&projectionMatrix,(float)viewport.Width,(float)viewport.Height,-25,25);
	HR = g_pDirect3D_Device->SetTransform(D3DTS_PROJECTION, &projectionMatrix);
	g_pDirect3D_Device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
	if(HR!=D3D_OK)
		return false;

	if(g_pDirect3D_Device)
	{
		vBuffer.Create(g_pDirect3D_Device,true);
		vTextureBuffer.Create(g_pDirect3D_Device,true);
	}
	return true;
}
void Renderer::Draw(D3DVERTEX* vertexCollection,D3DPRIMITIVETYPE ePrim,unsigned int uiVertexCount){	
	vBuffer.Bind();
	UnBindTexture();
	vBuffer.Draw(vertexCollection,ePrim,uiVertexCount);
}
void Renderer::Draw(TEXTUREVERTEX* vertexCollection,D3DPRIMITIVETYPE ePrim,unsigned int uiVertexCount){	
	vTextureBuffer.Bind();
	vTextureBuffer.Draw(vertexCollection,ePrim,uiVertexCount);
}
void Renderer::StartFrame(){
	
	HRESULT hr=g_pDirect3D_Device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(50, 50, 255), 1.0f, 0);
	g_pDirect3D_Device->BeginScene();
}
void Renderer::EndFrame(){
	g_pDirect3D_Device->EndScene();
	g_pDirect3D_Device->Present(NULL, NULL, NULL, NULL);
}

void Renderer::SetMatrixMode(MATRIX_MODE mode){
	currentMatrixMode=mode;
}

void Renderer::LoadIdentity(){
	D3DXMATRIX tempMatrix;

	D3DXMatrixIdentity(&tempMatrix);

	if(currentMatrixMode == View){
		D3DXVECTOR3 eyePos(0,0,-1);
		D3DXVECTOR3 lookPos(0,0,0);
		D3DXVECTOR3 upVector(0,1,0);

		D3DXMatrixLookAtLH(&tempMatrix, &eyePos, &lookPos, &upVector);
	}

	D3DTRANSFORMSTATETYPE matMode = static_cast<D3DTRANSFORMSTATETYPE>(currentMatrixMode);

	g_pDirect3D_Device->SetTransform(matMode, &tempMatrix);
}

void Renderer::SetViewportPosition(){
	D3DXMATRIX matrix;
	D3DXVECTOR3 lookPos;

	lookPos.x = viewerPos.x;
	lookPos.y = viewerPos.y;
	lookPos.z = 0;

	D3DXMatrixLookAtLH(&matrix,&viewerPos,&lookPos,&viewerUp);
	g_pDirect3D_Device->SetTransform(D3DTS_VIEW, &matrix);
}

void Renderer::RotateX(float angle){
	D3DXMATRIX tempMatrix;

	D3DXMatrixRotationX(&tempMatrix,angle);

	D3DTRANSFORMSTATETYPE matMode = static_cast<D3DTRANSFORMSTATETYPE>(currentMatrixMode);

	g_pDirect3D_Device->MultiplyTransform(matMode,&tempMatrix);
}

void Renderer::RotateY(float angle){
	D3DXMATRIX tempMatrix;

	D3DXMatrixRotationY(&tempMatrix,angle);

	D3DTRANSFORMSTATETYPE matMode = static_cast<D3DTRANSFORMSTATETYPE>(currentMatrixMode);

	g_pDirect3D_Device->MultiplyTransform(matMode,&tempMatrix);
}

void Renderer::RotateZ(float angle){
	D3DXMATRIX tempMatrix;

	D3DXMatrixRotationZ(&tempMatrix,angle);

	D3DTRANSFORMSTATETYPE matMode = static_cast<D3DTRANSFORMSTATETYPE>(currentMatrixMode);

	g_pDirect3D_Device->MultiplyTransform(matMode,&tempMatrix);
}

void Renderer::Translate(float x,float y,float z){
	D3DXMATRIX tempMatrix;

	D3DXMatrixTranslation(&tempMatrix,x,y,z);

	D3DTRANSFORMSTATETYPE matMode = static_cast<D3DTRANSFORMSTATETYPE>(currentMatrixMode);

	g_pDirect3D_Device->MultiplyTransform(matMode,&tempMatrix);
}

void Renderer::Scale(float width,float height){
	D3DXMATRIX tempMatrix;

	D3DXMatrixScaling(&tempMatrix,width,height,1.0f);

	D3DTRANSFORMSTATETYPE matMode = static_cast<D3DTRANSFORMSTATETYPE>(currentMatrixMode);

	g_pDirect3D_Device->MultiplyTransform(matMode,&tempMatrix);
}

bool Renderer::LoadTexture(/*const char* _fileName*,*/ Texture::ptr texture){
	IDirect3DTexture9* bitmapTexture=NULL;
	D3DXIMAGE_INFO imageInfo;
	HRESULT hr;
	
	int red,green,blue;
	texture.get()->GetColorKey(red,green,blue);

	hr=D3DXCreateTextureFromFileEx(g_pDirect3D_Device,
		texture->GetFileName().c_str(),
		0,0,0,0,
		D3DFMT_UNKNOWN,D3DPOOL_MANAGED,
		D3DX_FILTER_NONE,D3DX_FILTER_NONE,
		D3DCOLOR_XRGB(red,green,blue),
		&imageInfo,
		NULL,
		&bitmapTexture);

	if(hr!=D3D_OK)
		return false;
		
	texture->SetWidht(imageInfo.Width);
	texture->SetHeight(imageInfo.Height);

	textureMap[texture->GetFileName()]=bitmapTexture;
	return 0;
}


bool Renderer::BindTexture(Texture::ptr _texture){
	IDirect3DTexture9* pkDXTexture = textureMap[_texture->GetFileName()];

	assert(pkDXTexture);
	
	HRESULT hr = g_pDirect3D_Device->SetTexture(0, pkDXTexture);
	if(hr!=D3D_OK)
		return false;
	return true;
}
void Renderer::UnBindTexture(){
	g_pDirect3D_Device->SetTexture(0,NULL);
}
